// Copyright 2017 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
#pragma once

#include "rpinterface.h"
#include "querynode.h"

// Juniper internal implementation of the IQueryVisitor interface as used by
// query providers (this is the initial 1.0.x structure implementation)

typedef juniper::QueryItem QueryItem;
typedef juniper::IQuery IQuery;
typedef juniper::QueryHandle QueryHandle;

class Matcher;

namespace juniper {
    class QueryModifier;
}

/** See IQueryVisitor for detailed interface description
 */
class QueryVisitor : public juniper::IQueryVisitor
{
public:
    QueryVisitor(const IQuery& query, QueryHandle* qhandle, juniper::QueryModifier & queryModifier);
    ~QueryVisitor();

    bool VisitAND(const QueryItem* item, int arity) override;
    bool VisitOR(const QueryItem* item, int arity) override;
    bool VisitANY(const QueryItem* item, int arity) override;
    bool VisitNEAR(const QueryItem* item, int arity, int limit) override;
    bool VisitWITHIN(const QueryItem* item, int arity, int limit) override;
    bool VisitRANK(const QueryItem* item, int arity) override;
    bool VisitPHRASE(const QueryItem* item, int arity) override;
    bool VisitANDNOT(const QueryItem* item, int arity) override;
    bool VisitTHRESHOLD(const QueryItem* item, int arity, int threshold) override;
    bool VisitOther(const QueryItem* item, int arity) override;
    void VisitKeyword(const QueryItem* item, const char* keyword,
                      const size_t length = 0, bool prefix = false, bool specialToken = false) override;

    /** Grab pointer to (and ownership of) the query structure generated by this visitor.
     *  The call releases the query structure from this visitor.
     * @return The root node in the generated query tree now to be managed and
     *    subsequently deleted by caller
     */
    QueryExpr* GetQuery();

protected:
    std::string get_index(const QueryItem* item);
private:
    // Helper functions/members for use during construction only.
    void update_parameters(const char* options);
    void insert(QueryExpr* expr);
    void postprocess_query();
    juniper::QueryModifier & _queryModifier;

    const IQuery* _fquery; // Temp.pointer to the input query (valid in constructor only..

    // Members valid after init..
    QueryExpr* _query;  // Root of query
    QueryExpr* _current;  // Current position in query tree
    QueryHandle* _qhandle;
    int _term_index;
    bool _got_stack; // Set when we have created a stack root

    QueryVisitor(QueryVisitor &);
    QueryVisitor &operator=(QueryVisitor &);
};


